module(..., package.seeall)

require "utils.oop"
require "utils.table"
require "moaix.input.common"


----------------------------------------------------------------------------------------------------
-- Setup module signals, channel, and callback binding shortcut functions
----------------------------------------------------------------------------------------------------
SIGNALS = {DOWN = "touch down",
           UP   = "touch up", 
           MOVE = "touch move"}
channel, bind_shortcuts = moaix.input.common.make_channel("touch", SIGNALS)
table.copy(bind_shortcuts, _M)  -- make bind shortcuts available at module level

----------------------------------------------------------------------------------------------------
-- Touch class
----------------------------------------------------------------------------------------------------
Touch = class("Touch")

function Touch.__init(id, x, y, tap_count)
    self.id = id
    self.x = x
    self.y = y
    self.dx = 0
    self.dy = 0
    self.down = true
    self.tap_count = tap_count
end

function Touch.move_to(self, x, y)
    self.dx = x - self.x
    self.dy = y - self.y
    self.x = x
    self.y = y
end

function Touch.end_at(self, x, y)
    self:move_to(x, y)
    self.down = false
end

function Touch.__tostring(self)
    return ("<%s#%s (%d taps) %s @(%s, %s)>"):format(self.__name, self.id, 
        self.tap_count, (self.down and "down" or "up"), self.x, self.y)
end

----------------------------------------------------------------------------------------------------
-- Module state variables and input handler
----------------------------------------------------------------------------------------------------
touches = {}  -- keep track of touches

function touch_handler(event_type, touch_index, x, y, tap_count)
    local touch = touches[touch_index]
    
    if event_type == MOAITouchSensor.TOUCH_DOWN then
        assert(touch == nil)
        touch = Touch(touch_index, x, y, tap_count)
        touches[touch_index] = touch
        channel:emit(SIGNALS.DOWN, {touch=touch})
        
    elseif event_type == MOAITouchSensor.TOUCH_MOVE then
        assert(touch.tap_count == tap_count)
        touch:move_to(x, y)
        channel:emit(SIGNALS.MOVE, {touch=touch})
        
    else
        assert(touch.tap_count == tap_count)
        touch:end_at(x, y)
        touches[touch_index] = nil
        channel:emit(SIGNALS.UP, {touch=touch})
    end
end

----------------------------------------------------------------------------------------------------
-- Link input handler to MOAI's touch device
----------------------------------------------------------------------------------------------------
function init()
    if MOAIInputMgr.device.touch == nil then
        print("WARNING: Touch unavailable.")
        return false
    else
        print("INFO: Setting up touch input handler...")
        MOAIInputMgr.device.touch:setCallback(touch_handler)
        return true
    end
end
